/**
 * 移动端摄像头调用工具
 * 提供拍照、录像、相册选择等功能
 * 
 * @author 项目开发团队
 * @version 1.0.0
 */

/**
 * 检查浏览器是否支持摄像头
 * @returns {boolean} 是否支持摄像头
 */
export const isCameraSupported = () => {
  return !!(navigator.mediaDevices && navigator.mediaDevices.getUserMedia);
};

/**
 * 检查浏览器是否支持文件输入
 * @returns {boolean} 是否支持文件输入
 */
export const isFileInputSupported = () => {
  return !!(window.File && window.FileReader && window.FileList && window.Blob);
};

/**
 * 获取摄像头权限
 * @param {Object} constraints 约束条件
 * @returns {Promise<MediaStream>} 媒体流
 */
export const requestCameraPermission = async (constraints = {}) => {
  const defaultConstraints = {
    video: {
      width: { ideal: 1280 },
      height: { ideal: 720 },
      facingMode: 'user' // 前置摄像头
    },
    audio: false
  };

  const finalConstraints = { ...defaultConstraints, ...constraints };

  try {
    const stream = await navigator.mediaDevices.getUserMedia(finalConstraints);
    return stream;
  } catch (error) {
    console.error('获取摄像头权限失败:', error);
    throw new Error('无法访问摄像头，请检查权限设置');
  }
};

/**
 * 停止媒体流
 * @param {MediaStream} stream 媒体流
 */
export const stopMediaStream = (stream) => {
  if (stream) {
    stream.getTracks().forEach(track => {
      track.stop();
    });
  }
};

/**
 * 从视频流中捕获图片
 * @param {HTMLVideoElement} video 视频元素
 * @param {Object} options 选项
 * @returns {Promise<string>} Base64图片数据
 */
export const captureImageFromVideo = (video, options = {}) => {
  return new Promise((resolve, reject) => {
    try {
      const canvas = document.createElement('canvas');
      const context = canvas.getContext('2d');
      
      // 设置画布尺寸
      canvas.width = video.videoWidth || video.clientWidth;
      canvas.height = video.videoHeight || video.clientHeight;
      
      // 绘制视频帧到画布
      context.drawImage(video, 0, 0, canvas.width, canvas.height);
      
      // 转换为Base64
      const quality = options.quality || 0.8;
      const imageData = canvas.toDataURL('image/jpeg', quality);
      
      // 移除data:image/jpeg;base64,前缀
      const base64 = imageData.split(',')[1];
      
      resolve(base64);
    } catch (error) {
      reject(error);
    }
  });
};

/**
 * 创建文件输入元素
 * @param {Object} options 选项
 * @returns {HTMLInputElement} 文件输入元素
 */
export const createFileInput = (options = {}) => {
  const input = document.createElement('input');
  input.type = 'file';
  input.accept = options.accept || 'image/*';
  input.capture = options.capture || 'environment'; // environment: 后置摄像头, user: 前置摄像头
  input.style.display = 'none';
  
  return input;
};

/**
 * 选择图片文件
 * @param {Object} options 选项
 * @returns {Promise<File>} 选择的文件
 */
export const selectImageFile = (options = {}) => {
  return new Promise((resolve, reject) => {
    const input = createFileInput(options);
    
    input.onchange = (event) => {
      const file = event.target.files[0];
      if (file) {
        resolve(file);
      } else {
        reject(new Error('未选择文件'));
      }
    };
    
    input.onerror = () => {
      reject(new Error('文件选择失败'));
    };
    
    // 添加到DOM并触发点击
    document.body.appendChild(input);
    input.click();
    
    // 清理
    setTimeout(() => {
      document.body.removeChild(input);
    }, 1000);
  });
};

/**
 * 将文件转换为Base64
 * @param {File} file 文件
 * @returns {Promise<string>} Base64数据
 */
export const fileToBase64 = (file) => {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = () => {
      const base64 = reader.result.split(',')[1];
      resolve(base64);
    };
    reader.onerror = reject;
    reader.readAsDataURL(file);
  });
};

/**
 * 压缩图片
 * @param {File} file 原始文件
 * @param {Object} options 压缩选项
 * @returns {Promise<File>} 压缩后的文件
 */
export const compressImage = (file, options = {}) => {
  return new Promise((resolve, reject) => {
    const canvas = document.createElement('canvas');
    const context = canvas.getContext('2d');
    const img = new Image();
    
    img.onload = () => {
      try {
        const { maxWidth = 1280, maxHeight = 720, quality = 0.8 } = options;
        
        // 计算压缩后的尺寸
        let { width, height } = img;
        if (width > maxWidth || height > maxHeight) {
          const ratio = Math.min(maxWidth / width, maxHeight / height);
          width *= ratio;
          height *= ratio;
        }
        
        // 设置画布尺寸
        canvas.width = width;
        canvas.height = height;
        
        // 绘制图片
        context.drawImage(img, 0, 0, width, height);
        
        // 转换为Blob
        canvas.toBlob((blob) => {
          if (blob) {
            const compressedFile = new File([blob], file.name, {
              type: 'image/jpeg',
              lastModified: Date.now()
            });
            resolve(compressedFile);
          } else {
            reject(new Error('图片压缩失败'));
          }
        }, 'image/jpeg', quality);
      } catch (error) {
        reject(error);
      }
    };
    
    img.onerror = () => {
      reject(new Error('图片加载失败'));
    };
    
    img.src = URL.createObjectURL(file);
  });
};

/**
 * 获取设备信息
 * @returns {Object} 设备信息
 */
export const getDeviceInfo = () => {
  const userAgent = navigator.userAgent;
  
  return {
    isMobile: /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(userAgent),
    isIOS: /iPad|iPhone|iPod/.test(userAgent),
    isAndroid: /Android/.test(userAgent),
    isTouchDevice: 'ontouchstart' in window || navigator.maxTouchPoints > 0,
    userAgent
  };
};

/**
 * 检查是否为HTTPS环境
 * @returns {boolean} 是否为HTTPS
 */
export const isHTTPS = () => {
  return location.protocol === 'https:';
};

/**
 * 显示摄像头权限提示
 * @param {Function} onGranted 授权成功回调
 * @param {Function} onDenied 授权拒绝回调
 */
export const showCameraPermissionDialog = (onGranted, onDenied) => {
  const dialog = document.createElement('div');
  dialog.innerHTML = `
    <div style="
      position: fixed;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      background: rgba(0, 0, 0, 0.5);
      display: flex;
      align-items: center;
      justify-content: center;
      z-index: 10000;
    ">
      <div style="
        background: white;
        border-radius: 12px;
        padding: 24px;
        margin: 20px;
        max-width: 400px;
        text-align: center;
      ">
        <h3 style="margin: 0 0 16px 0; color: #333;">摄像头权限</h3>
        <p style="margin: 0 0 20px 0; color: #666; line-height: 1.5;">
          需要访问您的摄像头进行人脸识别，请允许摄像头权限。
        </p>
        <div style="display: flex; gap: 12px; justify-content: center;">
          <button id="camera-deny" style="
            padding: 8px 16px;
            border: 1px solid #d9d9d9;
            background: white;
            border-radius: 6px;
            cursor: pointer;
          ">拒绝</button>
          <button id="camera-grant" style="
            padding: 8px 16px;
            border: none;
            background: #007bff;
            color: white;
            border-radius: 6px;
            cursor: pointer;
          ">允许</button>
        </div>
      </div>
    </div>
  `;
  
  document.body.appendChild(dialog);
  
  // 绑定事件
  dialog.querySelector('#camera-grant').onclick = () => {
    document.body.removeChild(dialog);
    onGranted();
  };
  
  dialog.querySelector('#camera-deny').onclick = () => {
    document.body.removeChild(dialog);
    onDenied();
  };
};

/**
 * 移动端摄像头调用封装
 * @param {Object} options 选项
 * @returns {Promise<File>} 拍摄的图片文件
 */
export const capturePhoto = async (options = {}) => {
  const deviceInfo = getDeviceInfo();
  
  // 检查HTTPS
  if (!isHTTPS() && !location.hostname.includes('localhost')) {
    throw new Error('摄像头功能需要HTTPS环境');
  }
  
  // 检查设备支持
  if (!deviceInfo.isMobile) {
    throw new Error('此功能仅支持移动设备');
  }
  
  // 检查文件输入支持
  if (!isFileInputSupported()) {
    throw new Error('浏览器不支持文件输入');
  }
  
  try {
    // 选择图片文件
    const file = await selectImageFile({
      accept: 'image/*',
      capture: options.capture || 'environment'
    });
    
    // 压缩图片
    const compressedFile = await compressImage(file, {
      maxWidth: options.maxWidth || 1280,
      maxHeight: options.maxHeight || 720,
      quality: options.quality || 0.8
    });
    
    return compressedFile;
  } catch (error) {
    console.error('拍照失败:', error);
    throw error;
  }
};

export default {
  isCameraSupported,
  isFileInputSupported,
  requestCameraPermission,
  stopMediaStream,
  captureImageFromVideo,
  createFileInput,
  selectImageFile,
  fileToBase64,
  compressImage,
  getDeviceInfo,
  isHTTPS,
  showCameraPermissionDialog,
  capturePhoto
};


